﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenSSL.X509;
using Sicurezza.CA.DataProvider;
using OpenSSL.Crypto;
using OpenSSL.Core;
using System.IO;
using System.Configuration;
using System.Web;
using Sicurezza.Entita;

namespace Sicurezza.CA.Manager
{
    public class SSLManager
    {
        private static SSLDataProvider dataProvider = new SSLDataProvider();
        private static X509Certificate CaCertificate = X509Manager.GetCaCertificate();


        public static void CreateCertificate(int ReqId, int days)
        {
            X509Request r = new X509Request(FileManager.LoadRequest(ReqId));
            BuildCertificate("req-"+ReqId, r,days);

        }

        public static void BuildCertificate(string ReqId, X509Request r, int days)
        {
            DateTime notBefore = DateTime.Now;
            DateTime notAfter = notBefore + new TimeSpan(days, 0, 0, 0);

            int ProfileId = ProfileManager.GetId(r.Subject);
            int serial = dataProvider.Save(ReqId, ProfileId, r, notBefore, notAfter);

            X509Name issuer = CaCertificate.Subject;

            X509Name subject = new X509Name();
            subject.Common = r.Subject.Common;
            subject.Country = r.Subject.Country;
            subject.Organization = r.Subject.Organization;
            subject.OrganizationUnit = r.Subject.OrganizationUnit;


            X509Certificate cert = new X509Certificate(serial,
                                                        subject,
                                                        issuer,
                                                        r.PublicKey,
                                                        notBefore,
                                                        notAfter);

            string keyUsage = r.Subject.GetTextByName("keyUsage");
            string subjectAltName = r.Subject.GetTextByName("subjectAltName");
            if (!string.IsNullOrEmpty(keyUsage))
            {
                X509Extension ext = new X509Extension(null, null, "keyUsage", false, keyUsage);
                cert.AddExtension(ext);
            }
            if (!string.IsNullOrEmpty(subjectAltName))
            {
                X509Extension ext = new X509Extension(null, null, "subjectAltName", false, subjectAltName);
                cert.AddExtension(ext);
            }

            cert.Sign(KeyManager.PrivateKey, MessageDigest.SHA1);

            FileManager.SaveCertificate(cert);

        }


        

        public static SignedMessage SignMessage(string message)
        {
            if (!string.IsNullOrEmpty(message))
            {
                SignedMessage sm = new SignedMessage();
                sm.Message = message;
                MessageDigestContext mdc = new MessageDigestContext(MessageDigest.SHA1);
                sm.Signature = mdc.Sign(ASCIIEncoding.ASCII.GetBytes(message), KeyManager.PrivateKey);
                return sm;
            }
            else
                return null;
        }
        public static string GetCertificate(string ReqId)
        {
            int certId = dataProvider.GetCertificate(ReqId);
            if (certId > 0)
                return FileManager.LoadCertificate(certId);
            else
                return null;

        }

        public static bool CheckSign(string message, int CertificateSerial, byte[] sign)
        {
            string cert = FileManager.LoadCertificate(CertificateSerial);
            X509Certificate certificate = new X509Certificate(new BIO(cert));
            MessageDigestContext mdc = new MessageDigestContext(MessageDigest.SHA1);
            return mdc.Verify(ASCIIEncoding.ASCII.GetBytes(message), sign, certificate.PublicKey);
        }

        public static void SaveRevokeRequest(string certificate)
        {
            X509Certificate cert = new X509Certificate(new BIO(certificate));
            int RevId = dataProvider.SaveRevokeRequest(cert);
            FileManager.SaveRevoke(RevId, cert);
        }

        

        

        public static bool Exist(X509Name x509Name, int ProfileId)
        {
            return dataProvider.Exist(x509Name, ProfileId);
        }


        public static List<Pair> GetAll(bool signature, bool encipher)
        {
            List<int> serials = dataProvider.GetAll(signature, encipher);
            List<Pair> recipients = new List<Pair>();
            for (int i = 0; i < serials.Count; i++)
			{
                Pair p = new Pair();
                X509Name n = ProfileManager.Get(serials[i]);
                p.key = serials[i].ToString();
                p.value = n.ToString().Replace("subjectAltName","Email");
                
                recipients.Add(p);
			}

            return recipients;
        }
    }
}
